/* Echo
   (c)2002 Trilinear
*/



#ifndef WIN32
#include <kos.h>
#endif

#include "echo.h"
#include "agm.h"
#include <GL/gl.h>

inline void CommonTexParams() {
#ifndef WIN32
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_FILTER, GL_FILTER_BILINEAR);
#endif
}

void DrawChar(float x, float y, float z, char Letter) 
{
	if (Letter>=0x20) {
		float u=((float)((Letter-0x20)%12))/12.0f;//12 letters across
		float v=((float)((Letter-0x20)/12))/8.0f;//8 letters down

	//	glEnable(GL_KOS_AUTO_UV);
		glPushMatrix();
			glTranslatef(x, y, z);

			glScalef(.5f, 1, 1);

			glBegin(GL_TRIANGLES);
			
			glTexCoord2f(u+(1.0f/12.0f),v+(1.0f/8.0f));
			glVertex3f(1,  -1,     0.0f);
			glTexCoord2f(u,v+(1.0f/8.0f));
			glVertex3f(-1, -1, 0.0f);
			glTexCoord2f(u,v);
			glVertex3f(-1, 1, 0.0f);

			glTexCoord2f(u+(1.0f/12.0f),v+(1.0f/8.0f));
			glVertex3f(1, -1,      0.0f);
			glTexCoord2f(u,v);
			glVertex3f(-1, 1, 0.0f);
			glTexCoord2f(u+(1.0f/12.0f),v);
			glVertex3f(1, 1,      0.0f);

			glEnd();

		glPopMatrix();
	}
}


static char strbuf[1024];

void DrawString(float x, float y, float z, char *fmt, ...) {
	va_list args;
	char *s=0;
	
	va_start(args, fmt);
#ifndef WIN32
	vsprintf(strbuf, fmt, args);
#else
	vsprintf_s(strbuf, 1024, fmt, args);
#endif
	va_end(args);

	glBindTexture(GL_TEXTURE_2D, texletters);
	CommonTexParams();
	s = strbuf;

	while (*s) {
		if (*s == ' ') {
			x += 0.8f; s++;
		} else{
			DrawChar(x+=0.8f, y, z, *s++);
		}
	}
}

//return 0-normal 2-quit
int Menu() {
	int button=1;
	int Selection=0;
	int LevelSelection=1;

	while(1) {
		if (SystemUpdate()) {return 2;}
		
		if (cont_get_cond(c, &cond) < 0) {
			printf("Error reading controller\n");
			break;
		}

		if (!(cond.buttons & CONT_DPAD_LEFT)) {
			if (Selection==2 && button==0) {
				LevelSelection--;
				if (LevelSelection<1) LevelSelection=1;
				button=1;
			}
		}else if (!(cond.buttons & CONT_DPAD_RIGHT)) {
			if (Selection==2 && button==0) {
				LevelSelection++;
				if (LevelSelection>9) LevelSelection=9;
				button=1;
			}
		}else if (!(cond.buttons & CONT_DPAD_DOWN)) {
			if (button==0){
				Selection++;if (Selection>3) Selection=3;
				button=1;
			}
		}else if (!(cond.buttons & CONT_DPAD_UP)) {
			if (button==0) {
				Selection--;if (Selection<0) Selection=0;
				button=1;
			}
		}else if (!(cond.buttons & CONT_B)) {
			if (button==0) {
				break;
			}
		}else if (!(cond.buttons & CONT_A)) {
			if (Selection==0 && button==0) {
				if (OWunlock) OWunlock=0;
				else OWunlock=1;
				button=1;
			}
			if (Selection==3) return 2;
//			if (Selection==4) return 2;
		}else button=0;

		if (!(cond.buttons & CONT_START) && !(cond.buttons & CONT_Y))
			return 1;

		glKosBeginFrame();

		glLoadIdentity();
		glTranslatef(0, 0, -40);

		glKosFinishList();
		DrawString(-10, 2, 0, VERSIONSTRING);
		if (OWunlock==1) {
			DrawString(-10, 0, 0, "Relock Overworld");
		}else{
			DrawString(-10, 0, 0, "Unlock Overworld");
		}
		DrawString(-10, -4, 0, "Top Score Lev%d: %d ",LevelSelection, levelscores[LevelSelection]);
		DrawString(-10, -6, 0, "Quit Game");
		DrawString(-10, -8, 0, "Press B to exit menu");
		DrawString(-11.5,-2*(float)Selection,0,">");

		glKosFinishFrame();

	}
	return 0;
}



#ifndef WIN32
void loadpng(const char *fn, uint32 alpha, GLuint *txr) {
	uint32 txaddr, w, h;

//	txaddr = ta_txr_allocate(w * h *2);
//	png_to_texture(*fn, txaddr, PNG_NO_ALPHA);

	png_load_texture(fn, &txaddr, alpha, &w, &h);
	glGenTextures(1, txr);
	glBindTexture(GL_TEXTURE_2D, *txr);
	if (alpha == PNG_NO_ALPHA) glKosTex2D(GL_RGB565_TWID, w, h, (char*)txaddr);
	if (alpha == PNG_MASK_ALPHA) glKosTex2D(GL_ARGB1555_TWID, w, h, (char*)txaddr);
 	if (alpha == PNG_FULL_ALPHA) glKosTex2D(GL_ARGB4444_TWID, w, h, (char*)txaddr);
}

void loadjpg(const char *fn, uint32 width, GLuint *txr) {
	uint32 txaddr;

	txaddr = (uint32)ta_txr_allocate(width * width * 2);
//	png_to_texture(*fn, txaddr, PNG_NO_ALPHA);

	jpeg_to_texture(fn, txaddr, width, 1);
	glGenTextures(1, txr);
	glBindTexture(GL_TEXTURE_2D, *txr);
	glKosTex2D(GL_RGB565_TWID, width, width, (char*)txaddr);

}
#endif

inline void DrawNumber(int amount) {
	float x=((float)((amount%10)%10))/10;
	float y=((float)((amount%10)/10))/10;

//	glEnable(GL_KOS_AUTO_UV);

	glBegin(GL_TRIANGLES);


	glTexCoord2f(x+.1f,y+.25f);
	glVertex3f(1,  -1,     0.0f);
	glTexCoord2f(x,y+.25f);
	glVertex3f(-1, -1, 0.0f);
	glTexCoord2f(x,y);
	glVertex3f(-1, 1, 0.0f);

	glTexCoord2f(x+.1f,y+.25f);
	glVertex3f(1, -1,      0.0f);
	glTexCoord2f(x,y);
	glVertex3f(-1, 1, 0.0f);
	glTexCoord2f(x+.1f,y);
	glVertex3f(1, 1,      0.0f);

	glEnd();
//	glDisable(GL_KOS_AUTO_UV);

}

inline void DrawPanel(int score,int lives) {
	glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

	
	glPushMatrix();
		glLoadIdentity();
		glTranslatef(0, 0, -4.1f);

		glScalef(0.13f, 0.18f, 1.0f);

		glPushMatrix();
			glTranslatef(-10, 5.7f, -.1f);
			glScalef(1.0f, 0.8f, 1.0f);
			glBegin(GL_TRIANGLES);
				glTexCoord2f(.5f,1);
				glVertex3f(1,  -1,     0.0f);
				glTexCoord2f(0,1);
				glVertex3f(-1, -1, 0.0f);
				glTexCoord2f(0,.5f);
				glVertex3f(-1, 1, 0.0f);

				glTexCoord2f(.5f,1);
				glVertex3f(1, -1,      0.0f);
				glTexCoord2f(0,.5f);
				glVertex3f(-1, 1, 0.0f);
				glTexCoord2f(.5f,.5f);
				glVertex3f(1, 1,      0.0f);
			glEnd();
		glPopMatrix();
		
		glPushMatrix();
			glTranslatef(-8, 5.5, -.1f);
			if (lives/10>0) {
				DrawNumber(lives/10);
				glTranslatef(1.7f, 0, 0);
			}
			DrawNumber(lives);
		glPopMatrix();
		
		glPushMatrix();
			glTranslatef(4, 5.7f, -.1f);
			glScalef(1.0f, 0.8f, 1.0f);
			glBegin(GL_TRIANGLES);
				glTexCoord2f(1,1);
				glVertex3f(1,  -1,     0.0f);
				glTexCoord2f(.5f,1);
				glVertex3f(-1, -1, 0.0f);
				glTexCoord2f(.5f,.5f);
				glVertex3f(-1, 1, 0.0f);

				glTexCoord2f(1,1);
				glVertex3f(1, -1,      0.0f);
				glTexCoord2f(.5f,.5f);
				glVertex3f(-1, 1, 0.0f);
				glTexCoord2f(1,.5f);
				glVertex3f(1, 1,      0.0f);
			glEnd();
		glPopMatrix();

		glPushMatrix();
			glTranslatef(6, 5.5, -.1f);
			if (score/1000>0) {
				DrawNumber(score/1000);
				glTranslatef(1.7f, 0, 0);
			}
			if (score/100>0) {
				DrawNumber(score/100);
				glTranslatef(1.7f, 0, 0);
			}
			if (score/10>0) {
				DrawNumber(score/10);
				glTranslatef(1.7f, 0, 0);
			}
			DrawNumber(score);
		glPopMatrix();
	glPopMatrix();
}


vector W,W0,D,U,V,N,P,PT1,PT2,PT3;
//R1=start segment, R2=end segment, r3=intersection point(if any)
//return 0-no collision, 1=collision
int GroundCollison(vector* R1,vector* R2,vector* R3,tgmmodel* tgm_model)
{
	tgmmodel* currobj;
	unsigned int i;
    float     r, a, b, minr;             // params to calc ray-plane intersect
	int retval=0;
	vector TempR3;

	minr=1.0f;// return the closest R

	SUB(D,*R2,*R1);//dir = R.P1 - R.P0;             // ray direction vector

	currobj=tgm_model;

	while (currobj!=0) {
		for (i=0;i<currobj->numTri;i++){

			PT1.x=(((float)currobj->points[currobj->tris[i].a].x)*currobj->scale.x+currobj->trans.x);
			PT1.y=(((float)currobj->points[currobj->tris[i].a].y)*currobj->scale.y+currobj->trans.y);
			PT1.z=(((float)currobj->points[currobj->tris[i].a].z)*currobj->scale.z+currobj->trans.z);
			PT2.x=(((float)currobj->points[currobj->tris[i].b].x)*currobj->scale.x+currobj->trans.x);
			PT2.y=(((float)currobj->points[currobj->tris[i].b].y)*currobj->scale.y+currobj->trans.y);
			PT2.z=(((float)currobj->points[currobj->tris[i].b].z)*currobj->scale.z+currobj->trans.z);
			PT3.x=(((float)currobj->points[currobj->tris[i].c].x)*currobj->scale.x+currobj->trans.x);
			PT3.y=(((float)currobj->points[currobj->tris[i].c].y)*currobj->scale.y+currobj->trans.y);
			PT3.z=(((float)currobj->points[currobj->tris[i].c].z)*currobj->scale.z+currobj->trans.z);

			// get triangle edge vectors and plane normal
			SUB(U,PT2,PT1);//u = T.V1 - T.V0;
			SUB(V,PT3,PT1);//v = T.V2 - T.V0;
			CROSS (N,U,V);//n = u * v;             // cross product

			if (FLOAT0CLIP(N.x)!=0 || FLOAT0CLIP(N.y)!=0 || FLOAT0CLIP(N.z)!=0) {// triangle is not degenerate
		
				SUB(W0,*R1,PT1);//w0 = R.P0 - T.V0;
				a = DOT(N,W0);
				b = DOT(N,D);

				if (FLOAT0CLIP(b) != 0 &&      // ray is not parallel to triangle plane
					FLOAT0CLIP(a) != 0) {               // ray dos not lie in triangle plane

					// get intersect point of ray with triangle plane
					r = -a / b; //r = -a / b;
					if ((r > 0.0f) && (r<minr))  {//ray intersects triangle plane in segment

						float    uu, uv, vv, wu, wv, d1;//   float    uu, uv, vv, wu, wv, D;

						SCALE(P, r, D)
						ADD(TempR3,*R1, P);//	*I = R.P0 + r * D;           // intersect point of ray and plane

						// is I inside T?
						uu = DOT(U,U);//uu = dot(u,u);
						uv = DOT(U,V);//uv = dot(u,v);
						vv = DOT(V,V);//vv = dot(v,v);
						SUB(W,TempR3,PT1);//	w = *I - T.V0;
						wu = DOT(W,U);//wu = dot(w,u);
						wv = DOT(W,V);//wv = dot(w,v);
						d1 = uv * uv - uu * vv;//D = uv * uv - uu * vv;

						// get and test parametric coords
						float s, t;//float s, t;
						s = (uv * wv - vv * wu) / d1;//s = (uv * wv - vv * wu) / D;
						if (s >= 0.0f && s <= 1.0f) {  //if (s < 0.0 || s > 1.0)  // I is inside T
							t = (uv * wu - uu * wv) / d1;//t = (uv * wu - uu * wv) / D;
							if (t >= 0.0f && (s + t) <= 1.0f) { //if (t < 0.0 || (s + t) > 1.0)// I is inside T
								minr=r;
								retval=1;
								R3->x=TempR3.x;
								R3->y=TempR3.y;
								R3->z=TempR3.z;
							}//endif
						}//endif
					}//intersection
				}//not disjoint
			}//tri not degenerate
		}//endfor
		currobj=(tgmmodel*)currobj->NextObj;
	}//endwhile
    return retval;
}



